import { lazyReportCache } from '../utils/report.js'
import { onCachePageshow, deepCopy, getPagePath, onHidden, isSupportPerformanceObserver } from '../utils/common.js'

/**
 * 布局偏移
 * */
export default function observeCLS() {
    if (!isSupportPerformanceObserver()) return
    
    onCachePageshow(() => {
        observeCLS()
    })

    let sessionValue = 0
    let sessionEntries = []
    const cls = {
        type: 'performance',
        subType: 'layout-shift',
        name: 'layout-shift',
        pagePath: getPagePath(),
        value: 0,
        entries: [],
        startTime: 0
    }

    const entryHandler = (list) => {
        const entries = list.getEntries()
        for (const entry of entries) {
            // 仅统计布局变化，不考虑最近的用户输入
            if (!entry.hadRecentInput) {
                const firstSessionEntry = sessionEntries[0]
                const lastSessionEntry = sessionEntries[sessionEntries.length - 1]
                
                // 如果输入发生在前一个输入后不到1秒，并且在会话首次进入后不到5秒，包括进入当前会话。否则，开始一个新的会话。
                if (
                    sessionValue
                    && entry.startTime - lastSessionEntry.startTime < 1000
                    && entry.startTime - firstSessionEntry.startTime < 5000
                ) {
                    sessionValue += entry.value
                    sessionEntries.push(formatCLSEntry(entry))
                } else {
                    sessionValue = entry.value
                    sessionEntries = [formatCLSEntry(entry)]
                }
                
                // 如果当前会话值大于当前CLS值，更新CLS及其相关条目。
                if (sessionValue > cls.value) {
                    cls.value = sessionValue
                    cls.entries = sessionEntries
                    cls.startTime = performance.now()
                    console.log(deepCopy(cls));
                    lazyReportCache(deepCopy(cls))
                }
            }
        }
    }

    const observer = new PerformanceObserver(entryHandler)
    observer.observe({ type: 'layout-shift', buffered: true })

    if (observer) {
        onHidden(() => {
            // observer.takeRecords 是 PerformanceObserver API 中的一个方法，用于获取当前已记录但尚未报告的性能条目，并清空记录队列。
            observer.takeRecords().map(entryHandler)
        })
    }
}

function formatCLSEntry(entry) {
    const result = entry.toJSON()
    Reflect.deleteProperty(result, 'sources')
    Reflect.deleteProperty(result, 'duration')
    return result
}
